#pragma once

#include <functional>
#include <opencv2/opencv.hpp>

#include <iostream>
#include <memory>
#include <opencv2/features2d/features2d.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/video/background_segm.hpp>
#include <stdio.h>
#include <vector>

//#include <conio.h>
#include <math.h>
#include <queue>
#include <unordered_map>

using namespace std;
using namespace cv;

struct AODInput {
  cv::Mat mat;
};
struct AODResult {
  cv::Rect rt;
  int type;
  int prop;
  int detectedFrameCounts;
};
struct AODOutput {
  cv::Mat mat;
  vector<AODResult> arrRes;
};

typedef function<void(AODOutput &)> CallBack;

#include <memory>
using namespace std;
class AbandonObjectDetectPrivate;
class AbandonObjectDetect {
public:
  AbandonObjectDetect(){};

  virtual ~AbandonObjectDetect(){};
  // callback为检测到事件时的回调函数
  void setCallBack(CallBack cb) { cb_ = cb; }
  virtual void detect(const AODInput &input){};
  virtual void setROI(cv::Rect rt) { ROI_ = rt; };

  // 超过一定时间报出事件
  virtual void setTimeThreshold(float fSec) {
    cout << "TimeThreshold fSec:" << fSec << endl;
    fTimeThreshold_ = fSec;
  };
  // 最短第二次报出事件时间
  virtual void setTimeGapThreshold(float fSec) {
    cout << "TimeGapThreshold fSec:" << fSec << endl;
    fTimeGapThreshold_ = fSec;
  };
  virtual void setAreaThresholdMin(int nSize) {
    cout << "AreaThresholdMin nSize:" << nSize << endl;
    nAreaThresholdMin_ = nSize;
  };
  virtual void setAreaThresholdMax(int nSize) {
    cout << "AreaThresholdMax nSize:" << nSize << endl;
    nAreaThresholdMax_ = nSize;
  };
  // true: use simple Tactics(超过阈值即可) false: (需要查找合适的大小)
  virtual void setTacticsFlag(bool bFlag) {
    cout << "TacticsFlag bFlag:" << bFlag << endl;
    bTacticsFlag_ = bFlag;
  };

  virtual void setarrRes(vector<AODResult> arrRes) { arrRes_ = arrRes; };

  // must be even
  //   void setNeedToResetNumber(int nCount);
  cv::Rect getROI() { return ROI_; };
  float getTimeThreshold() { return fTimeThreshold_; };
  float getTimeGapThreshold() { return fTimeGapThreshold_; };
  int getAreaThresholdMin() { return nAreaThresholdMin_; };
  int getAreaThresholdMax() { return nAreaThresholdMax_; };
  bool getTacticsFlag() { return bTacticsFlag_; };
  vector<AODResult> getarrRes() { return arrRes_; };

public:
  CallBack cb_;
  shared_ptr<AbandonObjectDetectPrivate> m_pHandle;

private:
  cv::Rect ROI_;
  float fTimeThreshold_ = 5.f;
  float fTimeGapThreshold_ = 120.f;
  int nAreaThresholdMin_ = 200;
  int nAreaThresholdMax_ = 20000;
  bool bTacticsFlag_ = true;
  vector<AODResult> arrRes_;
};
typedef shared_ptr<AbandonObjectDetect> AbandonObjectDetectPtr;
